//SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

import React, { useEffect, useState } from "react";
import { observer } from 'mobx-react';
import type { ServiceInfo, SpanInfo } from "@/api/dragonfly/trace";
import { list_span } from "@/api/dragonfly/trace";
import { useDragonFlyStores } from "../store";
import { get_session } from "@/api/user";
import { request } from "@/utils/request";
import { gen_access_token } from "@/api/project_server";
import { Descriptions, List, Popover } from "antd";


interface SpanTreeNode {
    span: SpanInfo;
    children: SpanTreeNode[];
}

interface ExtSpanInfo {
    span: SpanInfo;
    level: number;
}

interface TraceDetailProps {
    serviceInfo: ServiceInfo;
    traceId: string;
}

const TraceDetail = (props: TraceDetailProps) => {
    const appStore = useDragonFlyStores();

    const [rootSpan, setRootSpan] = useState<SpanInfo | null>(null);
    const [spanList, setSpanList] = useState<ExtSpanInfo[]>([]);

    const setup = (parentItem: SpanTreeNode, spanList: SpanInfo[], rootSpan: SpanInfo) => {
        for (const span of spanList) {
            if (span.parent_span_id == parentItem.span.span_id) {
                const spanNode: SpanTreeNode = {
                    span: span,
                    children: [],
                }
                setup(spanNode, spanList, rootSpan);
                parentItem.children.push(spanNode);
            }
        }
    };

    const walk = async (parentItem: SpanTreeNode, resultList: ExtSpanInfo[], level: number) => {
        resultList.push({
            span: parentItem.span,
            level: level,
        });
        for (const childItem of parentItem.children) {
            walk(childItem, resultList, level + 1);
        }
    };

    const init = async () => {
        if (appStore.remoteServer == null || appStore.remoteServer.basic_info.addr_list.length == 0) {
            return;
        }
        const sessionId = await get_session();
        const accessRes = await request(gen_access_token({
            session_id: sessionId,
            project_id: appStore.projectId,
            server_id: appStore.remoteServer.server_id,
        }));
        const res = await request(list_span(appStore.remoteServer.basic_info.addr_list[0], {
            access_token: accessRes.token,
            remote_id: appStore.remoteServer.server_id,
            service: props.serviceInfo,
            trace_id: props.traceId,
        }));

        res.span_list.sort((a, b) => a.start_time_stamp - b.start_time_stamp)

        let tmpRootSpan: SpanInfo | null = null;
        for (const span of res.span_list) {
            if (span.parent_span_id == "") {
                tmpRootSpan = span;
                break;
            }
        }
        if (tmpRootSpan == null) {
            return;
        }
        const rootItem: SpanTreeNode = {
            span: tmpRootSpan,
            children: [],
        };
        setup(rootItem, res.span_list, tmpRootSpan)
        const resultList: ExtSpanInfo[] = [];
        walk(rootItem, resultList, 0);
        setSpanList(resultList);
        setRootSpan(tmpRootSpan);
    };

    const calcLeft = (span: SpanInfo) => {
        if (rootSpan == null) {
            return undefined;
        }
        const rootConsume = rootSpan.end_time_stamp - rootSpan.start_time_stamp;
        if (rootConsume <= 0) {
            return undefined;
        }
        let spanOffset = span.start_time_stamp - rootSpan.start_time_stamp;
        if (spanOffset <= 0) {
            spanOffset = 0;
        }
        return `${spanOffset / rootConsume * 100}%`;
    }

    const calcWidth = (span: SpanInfo) => {
        if (rootSpan == null) {
            return undefined;
        }
        const rootConsume = rootSpan.end_time_stamp - rootSpan.start_time_stamp;
        if (rootConsume <= 0) {
            return undefined;
        }
        const spanConsume = span.end_time_stamp - span.start_time_stamp;
        if (spanConsume <= 0) {
            return undefined;
        }
        return `${spanConsume / rootConsume * 100}%`;
    };

    const getBgColor = (level: number) => {
        const colorList = ["#3f51b5", "#2196f3", "#03a9f4", "#00bcd4",
            "#009688", "#4caf50", "#8bc34a", "#cddc39", "#ffeb3b",
            "#ffc107", "#ff9800", "#ff5722", "#795548", "#607d8b"];
        return colorList[level % colorList.length];
    };

    useEffect(() => {
        init();
    }, [props.serviceInfo, props.traceId]);


    return (
        <>
            {rootSpan != null && (
                <List dataSource={spanList} pagination={false} renderItem={spanItem => (
                    <div key={spanItem.span.span_id} style={{ height: "70px", padding: "10px 10px", overflow: "hidden" }}>
                        <div style={{ paddingLeft: spanItem.level * 20, fontWeight: 500, fontSize: "20px" }}>{spanItem.span.span_name}</div>
                        <div style={{ backgroundColor: "#eee", width: "100%", position: "relative", height: "10px" }}>
                            <Popover placement="bottom" trigger="hover" content={
                                <Descriptions column={1} style={{ width: "400px" }} bordered labelStyle={{ width: "100px" }}>
                                    <Descriptions.Item label="时间偏移">{spanItem.span.start_time_stamp - rootSpan.start_time_stamp}ms</Descriptions.Item>
                                    <Descriptions.Item label="消耗时间">{spanItem.span.end_time_stamp - spanItem.span.start_time_stamp}ms</Descriptions.Item>
                                    {spanItem.span.attr_list.map(attrItem => (
                                        <Descriptions.Item key={`${attrItem.key}:${attrItem.value}`} label={attrItem.key}>
                                            {attrItem.value}
                                        </Descriptions.Item>
                                    ))}
                                </Descriptions>
                            }>
                                <div style={{
                                    position: "absolute", left: calcLeft(spanItem.span), width: calcWidth(spanItem.span), backgroundColor: getBgColor(spanItem.level),
                                    height: "10px", cursor: "pointer", borderRadius: "10px"
                                }} >
                                    <div style={{ marginTop: "10px", width: "100%", textWrap: "nowrap" }}>
                                        时间偏移:{spanItem.span.start_time_stamp - rootSpan.start_time_stamp}ms&nbsp;
                                        消耗时间:{spanItem.span.end_time_stamp - spanItem.span.start_time_stamp}ms
                                    </div>
                                </div>
                            </Popover>
                        </div>
                    </div>
                )} />
            )}
        </>
    );
};

export default observer(TraceDetail);